package com.atguigu.tingshu.user.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.atguigu.tingshu.album.client.TrackInfoFeignClient;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.model.user.UserInfo;
import com.atguigu.tingshu.model.user.UserPaidAlbum;
import com.atguigu.tingshu.model.user.UserPaidTrack;
import com.atguigu.tingshu.user.mapper.*;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.user.strategy.ItemTypeStrategy;
import com.atguigu.tingshu.user.strategy.StrategyFactory;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    @Autowired
    private UserInfoMapper userInfoMapper;
    @Resource
    private WxMaService wxMaService;
    @Resource
    private RabbitService rabbitService;
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private UserPaidAlbumMapper userPaidAlbumMapper;
    @Resource
    private UserPaidTrackMapper userPaidTrackMapper;
    @Resource
    private TrackInfoFeignClient trackInfoFeignClient;
    @Resource
    private VipServiceConfigMapper vipServiceConfigMapper;
    @Resource
    private UserVipServiceMapper userVipServiceMapper;
    @Resource
    private StrategyFactory strategyFactory;

    //    @Override
//    public Map<String, Object> wxLogin(String code) {
//        // 声明一个Map集合
//        HashMap<String, Object> map = new HashMap<>();
//        // 容器自己构建的对象缺少两个东西
//        // appid   secret
//        WxMaJscode2SessionResult wxMaJscode2SessionResult = null;
//        try {
//            wxMaJscode2SessionResult = wxMaService.jsCode2SessionInfo(code);
//        } catch (WxErrorException e) {
//            throw new RuntimeException(e);
//        }
//        // 获取微信用户对应的微信标识
//        String openid = wxMaJscode2SessionResult.getOpenid();
//        // 通过这个openId查询用户相关信息，如果有对应的信息 则说明此用户已经注册过了；
//        //  如果没有对应的信息 则说明此用户没有注册过，则需要注册用户信息，并且初始化账户金额  目的是留住用户
//        UserInfo userInfo = userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getWxOpenId, openid));
//        // 判断用户是否存在
//        if (null == userInfo){
//            // 第一次注册
//            //  发送消息实现初始化账户金额  rabbitmq
//            userInfo = new UserInfo();
//            userInfo.setWxOpenId(openid);
//            userInfo.setNickname("用户" + UUID.randomUUID().toString().replaceAll("-", ""));
//            userInfo.setAvatarUrl("https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");
//            userInfoMapper.insert(userInfo);
//            // 发送消息进行初始化账户金额
//            rabbitService.sendMessage(MqConst.EXCHANGE_USER, MqConst.ROUTING_USER_REGISTER, userInfo.getId());
//        }
//        // 直接存储到缓存里面 ，并返回一个token
//        String token = UUID.randomUUID().toString().replaceAll("-", "");
//        //	缓存key
//        String userLoginKey = RedisConstant.USER_LOGIN_KEY_PREFIX + token;
//        redisTemplate.opsForValue().set(userLoginKey,userInfo,RedisConstant.USER_LOGIN_KEY_TIMEOUT, TimeUnit.SECONDS);
//        //	存储数据
//        map.put("token",token);
//        //	返回数据
//        return map;
//    }
    @Override
    public Map<String, Object> wxLogin(String code) {    //	声明一个map 集合
        Map<String, Object> map = new HashMap<>();
        //	容器自己构建的对象缺少：appid secret
        WxMaJscode2SessionResult wxMaJscode2SessionResult = null;
        try {
            wxMaJscode2SessionResult = wxMaService.jsCode2SessionInfo(code);
        } catch (WxErrorException e) {
            throw new RuntimeException(e);
        }
        //	获取到了微信用户对应的微信标识
        String openid = wxMaJscode2SessionResult.getOpenid();
        //	通过这个openid 查询用户信息，如果有对应的信息记录，则说明用户已经注册过; 如果没有，则说明用户未注册过，实现注册功能，并初始化账户金额; 留住用户;
        UserInfo userInfo = userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getWxOpenId, openid));
        //	判断用户信息是否存在
        if (null == userInfo) {
            //	第一次注册;
            //	发送消息实现初始化账户信息；
            userInfo = new UserInfo();
            userInfo.setWxOpenId(openid);
            userInfo.setNickname("用户" + UUID.randomUUID().toString().replaceAll("-", ""));
            userInfo.setAvatarUrl("https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");
            //	添加到表中;
            userInfoMapper.insert(userInfo);
            //	发送一个消息，账户金额初始化;
            rabbitService.sendMessage(MqConst.EXCHANGE_USER, MqConst.ROUTING_USER_REGISTER, userInfo.getId());
        }
        //	直接存储到缓存，并返回一个token;
        String token = UUID.randomUUID().toString().replaceAll("-", "");
        //	缓存key
        String userLoginKey = RedisConstant.USER_LOGIN_KEY_PREFIX + token;
        redisTemplate.opsForValue().set(userLoginKey, userInfo, RedisConstant.USER_LOGIN_KEY_TIMEOUT, TimeUnit.SECONDS);
        //	存储数据
        map.put("token", token);
        //	返回数据
        return map;
    }

    @Override
    public void updateUserInfo(UserInfoVo userInfoVo, Long userId) {
        //	创建对象
        UserInfo userInfo = new UserInfo();
        //	属性拷贝：
        BeanUtils.copyProperties(userInfoVo, userInfo);
        userInfo.setId(userId);
        //	更新用户信息
        userInfoMapper.updateById(userInfo);
    }

    @Override
    public UserInfoVo getUserInfo(Long userId) {
        //	查询数据
        UserInfo userInfo = this.getById(userId);
        //	属性拷贝：
        UserInfoVo userInfoVo = new UserInfoVo();
        BeanUtils.copyProperties(userInfo, userInfoVo);
        //	返回数据
        return userInfoVo;
    }

    @Override
    public Map<Long, Integer> userIsPaidTrack(Long albumId, List<Long> trackIdList, Long userId) {
        // 创建map集合
        Map<Long, Integer> map = new HashMap<>();
        // 用户是否购买专辑  user_paid_album
        UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getUserId, userId).eq(UserPaidAlbum::getAlbumId, albumId));
        if (null != userPaidAlbum) {
            // 用户购买了专辑
            Map<Long, Integer> trackIdMap = trackIdList.stream().collect(Collectors.toMap(trackId -> trackId, trackId -> 1));
            return trackIdMap;
        } else {
            // 未购买专辑
            // 看是否购买声音  user_paid_track
            LambdaQueryWrapper<UserPaidTrack> userPaidTrackLambdaQueryWrapper = new LambdaQueryWrapper<>();
            userPaidTrackLambdaQueryWrapper.eq(UserPaidTrack::getUserId, userId).in(UserPaidTrack::getTrackId, trackIdList).eq(UserPaidTrack::getAlbumId, albumId);
            // 当前用户购买过安歇声音集合
//            List<UserPaidTrack> userPaidTrackList = userPaidTrackMapper.selectList(userPaidTrackLambdaQueryWrapper);
            // 转换
//            List<Long>  userPaidTrackList
            List<Long> userPaidTrackList = userPaidTrackMapper.selectList(userPaidTrackLambdaQueryWrapper).stream().map(UserPaidTrack::getTrackId).toList();
            // 判断
            for (Long trackId : trackIdList) {
                // 判断需要购买的声音列表集合trackIdList中有没有我们查到的已经购买过的声音ID
                // 有的话则不用在粗购买直接能看  尚未购买则需要在粗进行购买
                if (userPaidTrackList.contains(trackId)) {
                    // 已经购买过
                    map.put(trackId, 1);
                } else {
                    // 未购买过
                    map.put(trackId, 0);
                }
            }
        }
        // 数据返回
        return map;
    }

    @Override
    public Boolean isPaidAlbum(Long userId, Long albumId) {
        // 查询表中是否有记录
        LambdaQueryWrapper<UserPaidAlbum> userPaidAlbumLambdaQueryWrapper = new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getUserId, userId).eq(UserPaidAlbum::getAlbumId, albumId);
        return (null != userPaidAlbumMapper.selectOne(userPaidAlbumLambdaQueryWrapper));
    }

    @Override
    public List<Long> findUserPaidTrackList(Long albumId, Long userId) {
        //根据用户ID与专辑ID查询用户购买的声音ID集合
        LambdaQueryWrapper<UserPaidTrack> userPaidTrackLambdaQueryWrapper = new LambdaQueryWrapper<UserPaidTrack>().eq(UserPaidTrack::getUserId, userId).eq(UserPaidTrack::getAlbumId, albumId);
        List<Long> list = userPaidTrackMapper.selectList(userPaidTrackLambdaQueryWrapper).stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
        return list;
    }

    /**
     * 无策略模式与工厂模式代码  需要优化
     */
//    @Override
//    public int savePaidRecord(UserPaidRecordVo userPaidRecordVo) {
//        // 声明一个变量  进行返回结果赋值
//        int result = 0;
//
//        // 1.  根据itemType类型进行判断看是买的啥   专辑 声音 还是 vip
//
//        if (SystemConstant.ORDER_ITEM_TYPE_ALBUM.equals(userPaidRecordVo.getItemType())) {
//            //  买的是专辑
//            //  查看用户是否购买过此专辑
//            LambdaQueryWrapper<UserPaidAlbum> userPaidAlbumLambdaQueryWrapper = new LambdaQueryWrapper<>();
//            userPaidAlbumLambdaQueryWrapper.eq(UserPaidAlbum::getUserId, userPaidRecordVo.getUserId())
//                    .eq(UserPaidAlbum::getAlbumId, userPaidRecordVo.getItemIdList().get(0));
//            UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(userPaidAlbumLambdaQueryWrapper);
//            if (null == userPaidAlbum) {
//                // 用户没有购买过此专辑
//                //  创建一个新的对象 进行赋值 且插入数据库即可
//                UserPaidAlbum userPaidAlbum1 = new UserPaidAlbum();
//                userPaidAlbum1.setUserId(userPaidRecordVo.getUserId());
//                userPaidAlbum1.setAlbumId(userPaidRecordVo.getItemIdList().get(0));
//                userPaidAlbum1.setOrderNo(userPaidRecordVo.getOrderNo());
//                return result += userPaidAlbumMapper.insert(userPaidAlbum1);
//            }
//            return result;
//        } else if (SystemConstant.ORDER_ITEM_TYPE_TRACK.equals(userPaidRecordVo.getItemType())) {
//            //  买的是声音
//            // 避免重复购买声音
//            //  购买的声音ID列表是啥
//            List<Long> TrackIdFroItemIdList = userPaidRecordVo.getItemIdList();
//            //  根据声音ID其获取声音对象
//            Result<TrackInfo> trackInfoResult = trackInfoFeignClient.getTrackInfo(TrackIdFroItemIdList.get(0));
//            Assert.notNull(trackInfoResult, "远程调用声音服务获取数据失败");
//            TrackInfo trackInfo = trackInfoResult.getData();
//            Assert.notNull(trackInfo, "远程调用声音服务获取数据trackInfo失败");
//            // 查询 当前用户是否购买过声音
//            //  一样的就不需要进行插入  可能会涉及到退款 ；反之则插入数据 即可
//            LambdaQueryWrapper<UserPaidTrack> userPaidTrackLambdaQueryWrapper = new LambdaQueryWrapper<>();
//            userPaidTrackLambdaQueryWrapper.eq(UserPaidTrack::getUserId, userPaidRecordVo.getUserId())
//                    .eq(UserPaidTrack::getTrackId, userPaidRecordVo.getItemIdList().get(0));
//            List<UserPaidTrack> userPaidTrackList = userPaidTrackMapper.selectList(userPaidTrackLambdaQueryWrapper);
//            //  转换成我们想要的trackId 集合 用stream流进行转换
//            List<Long> userPaidTrackIdList = userPaidTrackList.stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
//            // 循环遍历  取差集进行插入
//            //  交集则进行退款   发送消息即可
//            for (Long trackId : TrackIdFroItemIdList) {
//                if (userPaidTrackIdList.contains(trackId)) {
//                    // 退款
//                    log.warn("重复购买进行退款----请注意账户消息" + trackId);
//                } else {
//                    //  插入数据
//                    UserPaidTrack userPaidTrack = new UserPaidTrack();
//                    userPaidTrack.setUserId(userPaidRecordVo.getUserId());
//                    userPaidTrack.setAlbumId(trackInfo.getAlbumId());
//                    userPaidTrack.setTrackId(trackId);
//                    userPaidTrack.setOrderNo(userPaidRecordVo.getOrderNo());
//                    return result += userPaidTrackMapper.insert(userPaidTrack);
//                }
//            }
//            return result;
//        } else {
////            (SystemConstant.ORDER_ITEM_TYPE_VIP.equals(userPaidRecordVo.getItemType()))
//            //  买的是vip
//            // 判断 是首次购买  还是进行续期
//            // 用什么进行判断  根据过期时间进行判断
//            // vipID  是啥
//            Long vipServiceConfigId = userPaidRecordVo.getItemIdList().get(0);
//            // 获取购买时间
//            VipServiceConfig vipServiceConfig = vipServiceConfigMapper.selectById(vipServiceConfigId);
//            Integer serviceMonth = vipServiceConfig.getServiceMonth();
//            //  未过期的vip才能进行续期
//            // 获取信息
//            UserInfo userInfo = userInfoMapper.selectById(userPaidRecordVo.getUserId());
//            // 声明过期时间   用户后续过期时间赋值使用
//            Date vipExpireTime = new Date();
//            if (1 == userInfo.getIsVip() && userInfo.getVipExpireTime().after(new Date())) {
//                //   未过期  进行续期
//                // 原来的过期时间上加上 又购买的时间即可
//                vipExpireTime = userInfo.getVipExpireTime();
//                // 日期如何进行计算  使用JDK8 自带的 进行即可 注意每一步用变量进行接收
//                LocalDateTime localDateTime = new LocalDateTime(vipExpireTime).plusMonths(serviceMonth);
////                int i = 1/0;
//                //  设置新的过期时间
//                vipExpireTime = localDateTime.toDate();
//            } else {
//                //  首次购买vip
//                // 过期时间就是当前系统时间加上购买时间
//                vipExpireTime = new LocalDateTime(vipExpireTime).plusMonths(serviceMonth).toDate();
//            }
//            // 添加对象 进行赋值
//            UserVipService userVipService = new UserVipService();
//            userVipService.setOrderNo(userPaidRecordVo.getOrderNo());
//            userVipService.setUserId(userPaidRecordVo.getUserId());
//            userVipService.setStartTime(new Date());
//            // 过期时间
//            userVipService.setExpireTime(vipExpireTime);
//            // 数据保存
//            result += userVipServiceMapper.insert(userVipService);
//            // user_info  进行更新
//            userInfo.setIsVip(1);
//            userInfo.setVipExpireTime(vipExpireTime);
//            result += userInfoMapper.updateById(userInfo);
//        }
//        // 数据返回
//        return result;
//    }


    @Override
    public int savePaidRecord(UserPaidRecordVo userPaidRecordVo) {
        ItemTypeStrategy strategy = strategyFactory.getStrategy(userPaidRecordVo.getItemType());
        return strategy.savePaidRecord(userPaidRecordVo);
    }

    @Override
    public void updateVipExpireStatus() {
        //  调用mapper 层;
        userInfoMapper.updateVipExpireStatus();
    }
}
